package com.hfy.music.service.impl;

import com.alibaba.fastjson.JSON;
import com.hfy.feign.IUserClient;
import com.hfy.model.Bo.SendUserNoticeBo;
import com.hfy.model.po.user.UserCommentPo;
import com.hfy.model.vo.CommentVo;
import com.hfy.music.mapper.CommentMapper;
import com.hfy.music.mapper.DetailMusicMapper;
import com.hfy.music.mapper.LikeMapper;
import com.hfy.music.service.CommentService;
import constants.RabbitConstants;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import result.Result;

import java.time.LocalDateTime;
import java.util.List;

import static constants.RedisConstants.*;

/**
 * @ author 韩
 * time: 2024/5/29 14:16
 */

@Service
public class CommentServiceImpl implements CommentService {

    @Autowired
    private CommentMapper commentMapper;

    @Autowired
    private LikeMapper likeMapper;

    @Autowired
    private DetailMusicMapper detailMusicMapper;

    @Autowired
    private IUserClient userClient;

    @Autowired
    private StringRedisTemplate redisTemplate;
    // rabbitmq的客户端依赖
    @Autowired
    private RabbitTemplate rabbitTemplate;


    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class AddCommentBo {
        private Integer id;
        private Integer biz;
        private Long account;
        private Integer bizId;
        private String content;
        private LocalDateTime now;
    }

    @Override
    @Transactional
    public Result addComment(Integer biz , Long account, Integer bizId, String content) {
        // 耦合了两个接口 一个是向音乐评论 一个是向评论评论
        // 该操作是向mysql的评论表里增添一条数据
        LocalDateTime now = LocalDateTime.now();

        AddCommentBo addCommentBo = new AddCommentBo(null, biz, account, bizId, content, now);
        commentMapper.addComment(addCommentBo);
        Integer commentId = addCommentBo.getId();
        Integer temp = commentMapper.selectCommentCount(biz, bizId);

        if (temp == null) {
            // 代表未评论过 直接创建插入 初始化数据
            commentMapper.insertCommentCount(biz,bizId);
        } else {
            // 向comment计数表里数量加1
            commentMapper.commentIncreaseOne(biz,bizId);
        }

        // 然后再删缓存
        if (biz == 0) {
            // 这是对音乐评论的业务
            redisTemplate.delete(MUSIC_COMMENT_KEY + bizId);
        } else {
            // 这是对评论评论的业务
            redisTemplate.delete(COMMENT_COMMENT_KEY + bizId);
        }
        // todo 向rabbitmq发送消息
        // 先构造msg，然后指定交换机和key
        if (biz == 1) {
            // 说明是二级评论，那么就要去查找父级的父级，也就是bizId的bizId
            Integer musicId = commentMapper.selectMusicIdByCommentId(bizId);
            SendUserNoticeBo message = new SendUserNoticeBo(null, account, bizId, commentId, musicId, 0);

            rabbitTemplate.convertAndSend(RabbitConstants.COMMON_NOTICE_SEND_DIRECT_EXCHANGE, RabbitConstants.COMMON_USER_NOTICE_SEND_KEY, JSON.toJSONString(message));
        }

        return Result.ok();
    }

    @Override
    public Result deleteComment(Integer commentId) {
        Integer musicId = commentMapper.selectMusicIdByCommentId(commentId);
        redisTemplate.opsForHash().increment(MUSIC_COMMENT_KEY,musicId.toString(),-1l);

        commentMapper.deleteComment(commentId);

        return Result.ok();
    }

    @Override
    public Result showComments(Integer biz, Integer bizId, Long account) {
        // 是对音乐进行评论的业务
        List<CommentVo> vos = commentMapper.queryComments(biz,bizId);
        // 还有avatar，username，likeCount，commentCount没有设置

        vos.forEach(vo -> {
            Integer commentId = vo.getId();
            String likeCount = redisTemplate.opsForValue().get(COMMENT_LIKE_KEY + commentId);
            String commentCount = redisTemplate.opsForValue().get(COMMENT_COMMENT_KEY + commentId);
            if (likeCount == null) {
                // 如果在redis中无法取到数据 就直接访问数据库获取计数数据，并同步到redis
                // 这里只能是1 因为只有一级评论 评论的对象是歌曲 也就是业务类型为0 而查询的是每条评论的信息 所以只能是为1
                Integer like = detailMusicMapper.queryLikeCount(1,commentId);
                // 需要默认给它置为0
                if(like == null) like = 0;
                Integer unlike = detailMusicMapper.queryUnlikeCount(1,commentId);
                if(unlike == null) unlike = 0;

                likeCount = String.valueOf(like - unlike);
                // 同步到redis
                redisTemplate.opsForValue().set(COMMENT_LIKE_KEY + commentId,likeCount);
            }
            if (commentCount == null) {
                // 如果在redis中无法取到数据 就直接访问数据库获取计数数据，并同步到redis
                Integer comment = detailMusicMapper.queryCommentCount(1,commentId);
                if(comment == null) comment = 0;
                Integer uncomment = detailMusicMapper.queryUncommentCount(1,commentId);
                if(uncomment == null) uncomment = 0;
                commentCount = String.valueOf(comment - uncomment);
                // 同步到redis
                redisTemplate.opsForValue().set(COMMENT_COMMENT_KEY + commentId,commentCount);
            }
            if (Integer.parseInt(likeCount) < 0 || Integer.parseInt(commentCount) < 0) {
                throw new RuntimeException("出现问题，点赞或评论数为负数");
            }
            vo.setLikeCount(Integer.valueOf(likeCount));
            vo.setCommentCount(Integer.valueOf(commentCount));

            // 再调用feign接口 获取avatar和username
            UserCommentPo info = userClient.getInfoByAccount(vo.getAccount());
            vo.setAvatar(info.getAvatar());
            vo.setUsername(info.getUsername());

            // 再去检查该账号有没有对其点过赞 去点赞记录表里找
            // 因为对象是评论 要检查评论的点赞业务 所以业务类型一定是1
            Integer temp = likeMapper.queryIsLikedByAccount(commentId, 1, account);
            // 证明没有搜寻到
            vo.setIsLiked(temp != null);
        });



        return Result.ok(vos);
    }
}
